import os, pickle, logging

from data import database, config

logger = logging.getLogger(__name__)

def repair_main_db():
    everything_okay = True

    #region Check structure
    logger.info('Checking database structure')
    if 'type' not in database:
        logger.warning('Database type set to \'main\'')
        database['type'] = 'main'
        everything_okay = False

    if database['type'] != 'main':
        logger.critical('The loaded database isn\'t the right type')
        everything_okay = False
        return everything_okay

    #region main
    if 'music' not in database:
        logger.warning('Database missing music field')
        database['music'] = {}
        everything_okay = False

    if 'artists' not in database:
        logger.warning('Database missing artists field')
        database['artists'] = {}
        everything_okay = False

    if 'albums' not in database:
        logger.warning('Database missing albums field')
        database['albums'] = {}
        everything_okay = False

    if 'genres' not in database:
        logger.warning('Database missing genres field')
        database['genres'] = {}
        everything_okay = False
    #endregion

    #region music
    logger.info('Checking track structure')
    for track_uuid in database['music']:
        logger.info('Checking track %s' % track_uuid)
        track = database['music'][track_uuid]
        if 'title' not in track:
            logger.error('Track missing title field')
            track['title'] = None
            everything_okay = False
        if 'artists' not in track:
            logger.error('Track missing artists field')
            track['artists'] = []
            everything_okay = False
        if 'album' not in track:
            logger.error('Track missing album field')
            track['album'] = None
            everything_okay = False
        if 'genre' not in track:
            logger.error('Track missing genre field')
            track['genre'] = None
            everything_okay = False
    #endregion

    #region albums
    logger.info('Checking album structure')
    for album_uuid in database['albums']:
        logger.info('Checking album %s' % album_uuid)
        album = database['albums'][album_uuid]
        if 'name' not in album:
            logger.error('Album missing name field')
            album['name'] = None
            everything_okay = False
        if 'artist' not in album:
            logger.error('Album missing artist field')
            album['artist'] = None
            everything_okay = False
    #endregion

    #region artists
    logger.info('Checking artist structure')
    for artist_uuid in database['artists']:
        logger.info('Checking artist %s' % artist_uuid)
        artist = database['artists'][artist_uuid]
        if 'name' not in artist:
            logger.error('Artist missing name field')
            artist['name'] = None
            everything_okay = False
    #endregion

    #region genres
    logger.info('Checking genre structure')
    for genre_uuid in database['genres']:
        logger.info('Checking genre %s' % genre_uuid)
        genre = database['genres'][genre_uuid]
        if 'name' not in genre:
            logger.error('Genre missing name field')
            genre['name'] = None
            everything_okay = False
    #endregion
    #endregion

    #region Check tracks
    tracks_to_destroy = set()
    logger.info('Checking tracks')
    for uuid in database['music']:
        logger.info('Checking track %s' % uuid)
        track = database['music'][uuid]
        logger.info('Correcting file path')
        track['path'] = track['path'].replace('\\', '/')

        #region Check if file exists
        logger.info('Checking if file exists')
        abs_track_path = os.path.join(config['files']['audio']['path'], track['path'])
        if not os.path.exists(abs_track_path):
            logger.error('Track file not found. Queueing the track to be removed for the database')
            tracks_to_destroy.add(uuid)
            everything_okay = False
            continue
        #endregion

        #region Check artists
        logger.info('Checking artists')
        if 'artists' in track:
            if type(track['artists']) == list:
                logger.info('Changing data type from list to set')
                track['artists'] = set(track['artists'])
            artists_removed = 0
            artists_to_remove = []
            for artist in track['artists']:
                if artist not in database['artists']:
                    artists_to_remove.append(artist)
            for artist in artists_to_remove:
                track['artists'].remove(artist)
                artists_removed += 1
            if artists_removed:
                logger.info('Removed %s non-existent artists' % artists_removed)
                everything_okay = False
        else:
            logger.error('Track missing artists field')
            track['artists'] = set()
        #endregion

        #region Check albums
        logger.info('Checking album')
        if 'album' in track:
            if track['album'] and track['album'] not in database['albums']:
                track['album'] = None
                logger.error('Track album doesn\'t exist in the database')
                everything_okay = False
        else:
            logger.error('Track missing album field')
            track['album'] = None
        #endregion

        #region Check genres
        if 'genre' in track:
            logger.info('Checking genre')
            if track['genre'] and track['genre'] not in database['genres']:
                track['genre'] = None
                logger.error('Track genre doesn\'t exist in the database')
                everything_okay = False
        else:
            logger.error('Track missing genre field')
            track['genre'] = None
        #endregion
    #endregion

    #region Destroy tracks
    if tracks_to_destroy:
        logger.info('Removing %s tracks from the database' % len(tracks_to_destroy))
        for track in tracks_to_destroy:
            del database['music'][track]
            logger.info('Removed %s from the database' % track)
        everything_okay = False
    else:
        logger.info('No tracks were removed from the database')
    #endregion

    #region Check album artists
    logger.info('Checking album artists')
    for uuid in database['albums']:
        if not album['artist']:
            continue
        if album['artist'] not in database['artists']:
            logger.error('Album %s referenced an artist that is not in the database' % uuid)
            album['artist'] = None
    #endregion

    if everything_okay:
        logger.info('Everything okay')

    return everything_okay

def repair_sync_db(path):
    everything_okay = True

    #region load database
    logger.info('Loading sync database')
    if os.path.exists(os.path.join(path, 'sync.pkl')):
        with open(os.path.join(path, 'sync.pkl'), 'rb') as f:
            db = pickle.load(f)
    else:
        logger.critical('Failed to load sync database')
        return
    #endregion

    #region check strucure
    logger.info('Checking database structure')
    if not 'type' in db:
        logger.warning('Database type set to \'sync\'')
        db['type'] = 'sync'
        everything_okay = False

    if not 'music' in db:
        logger.info('Database missing music field')
        db['music'] = {}
        everything_okay = False

    if not 'templates' in db:
        logger.info('Database missing templates field')
        db['templates'] = {}
        everything_okay = False

    if not 'path' in db['templates']:
        db['templates']['path'] = '%(album)s by %(albumArtist)s/%(title)s by %(artists)s.%(ext)s'

    if not 'overwrite' in db['music']:
        print('Database missing \'music\' \'overwrite\'')
        db['music']['overwrite'] = {}
        everything_okay = False

    if not 'tracks' in db['music']:
        print('Database missing \'music\' \'tracks\'')
        db['music']['tracks'] = {}
        everything_okay = False

    if not 'blacklist' in db['music']:
        print('Database missing \'music\' \'blacklist\'')
        db['music']['blacklist'] = {}
        everything_okay = False

    if not 'artist' in db['templates']:
        print('Database missing \'templates\' \'artist\'')
        db['templates']['artist'] = {}
        everything_okay = False

    if not 'metadata' in db['music']['overwrite']:
        print('Database missing \'music\' \'overwrite\' \'metadata\'')
        db['music']['overwrite']['metadata'] = True
        everything_okay = False

    if not 'path' in db['music']['overwrite']:
        print('Database missing \'music\' \'overwrite\' \'path\'')
        db['music']['overwrite']['path'] = True
        everything_okay = False

    if not 'seperator' in db['templates']['artist']:
        print('Database missing \'templates\' \'artist\' \'seperator\'')
        db['templates']['artist']['seperator'] = {}
        everything_okay = False

    if not 'filename' in db['templates']['artist']['seperator']:
        print('Database missing \'templates\' \'artist\' \'seperator\' \'filename\'')
        db['templates']['artist']['seperator']['filename'] = ', '
        everything_okay = False

    if not 'metadata' in db['templates']['artist']['seperator']:
        print('Database missing \'templates\' \'artist\' \'seperator\' \'metadata\'')
        db['templates']['artist']['seperator']['metadata'] = ';'
        everything_okay = False

    #region check tracks
    # print('Checking track structure')
    # for uuid in db['music']['tracks']:
    #     track = db['music']['tracks'][uuid]
    #endregion
    #endregion

    #region check files
    print('Checking files')
    to_remove = set()
    for uuid in db['music']['tracks']:
        sync_track = db['music']['tracks'][uuid]
        if not os.path.exists(os.path.join(path, sync_track['path'])):
            print('%s is missing it\'s sync file and will be queued for removal' % uuid)
            to_remove.add(uuid)
            everything_okay = False
        if not uuid in database['music']:
            print('%s wasn\'t found in the main database and will be queued for removal' % uuid)
            to_remove.add(uuid)
            everything_okay = False
        if uuid in db['music']['blacklist']:
            print('%s has been synced, but it\'s in the blacklist. It will be queued for removal' % uuid)
            to_remove.add(uuid)
            everything_okay = False
    #endregion

    #region remove files
    for uuid in to_remove:
        print('Removing track %s' % uuid)
        sync_track = db['music']['tracks'][uuid]
        if os.path.exists(os.path.join(path, sync_track['path'])):
            os.remove(os.path.join(path, sync_track['path']))
        del db['music']['tracks'][uuid]

    if to_remove:
        print('Removed %s tracks' % len(to_remove))
    #endregion

    if everything_okay:
        print('Everything okay')

    print('Dumping sync database')
    with open(os.path.join(path, 'sync.pkl'), 'wb') as f:
        pickle.dump(db, f)

    return everything_okay
